/*==============================================================*/
/* program: RootedTree.c                                        */
/* purpose: generating all rooted trees                         */
/* input  : n -- number of nodes                                */
/*          mc -- max number of children of a node              */
/*          lb,ub -- lower and upper bound on height            */
/* output : listing of rooted trees in relex order              */
/* date   : September 1995, updated Sept 2000                   */
/* programmers: Gang Li & Frank Ruskey                          */
/* algorithm: From the paper: G. Li and F. Ruskey,  "The        */
/*    Advantages of Forward Thinking in Generating Rooted and   */
/*    Free Trees", 10th Annual ACM-SIAM Symposium on Discrete   */
/*    Algorithms (SODA), (1999) S939-940.  See the web page at  */
/*    http://www.theory.csc.UVic.CA/~fruskey/                   */
/*      Publications/RootedFreeTree.html                        */
/* more info: See                                               */
/*    http://www.theory.csc.UVic.CA/inf/RootedTrees.html   */
/*==============================================================*/
#include <stdio.h>
#define MaxSize 64  /* max size of the tree */
#include <iostream>
using namespace std;

int
 n,                             /* number of nodes in a tree */
 par[MaxSize],                  /* parent position of i */
 L[MaxSize];                    /* level of node i      */
 unsigned __int64 num;          /* total number of trees */
 int mc,                        /* max number of children */
 chi[MaxSize],                  /* number of children of a node */
 nextp[MaxSize],                /* next good pos to add nodes */
 rChi[MaxSize],                 /* the right most child of node i */
 lb,                            /* lower bound of the height */
 ub;                            /* upper bound of the height */


const int maxN = 30;         // Code added by W. Bomfim
unsigned __int64 an;        // a(n)
unsigned int Grau[maxN+1]; // Grau[i], 1<=i<=N, is the degree of i.

void FindGrau(){
unsigned int u;
Grau[1] = 0;
for(u=2; u<=n; u++)
    Grau[u] = 1;
for(u=1; u<=n; u++)
    Grau[par[u]]++;
}

void inicialize(){
an = 0;
FindGrau();
}

unsigned int Wiener_index(){
static unsigned int W, u, v, i, cGrau[maxN+1],
                    Q[maxN], F, R,
                    Order[maxN+1];
F = R = 0; W = 0;
for(u=1; u<=n; u++){
    Order[u] = 1;
    if(Grau[u]==1){
        Q[R] = u; R++;}
    else cGrau[u] = Grau[u];
    }
for(i=1; i<n; i++){
    u = Q[F]; F++;
    v = par[u];
    Order[v] = Order[v] + Order[u];
    cGrau[v]--;
    if(cGrau[v]==1){
        Q[R] = v; R++;}
    W += Order[u] * (n-Order[u]);
    }
return W;
}

void PrintIt() {
num++;
if(num == 1)
    inicialize();
an += Wiener_index();
}// End of code added by W. Bomfim

void Gen( int p, int s, int cL ) {// Added instructions to modify the array Grau. - W. Bomfim
  int np, temp;

  if (p > n) PrintIt();
  else {
    if (cL==0 && p <= ub+2 ) {Grau[par[p]]--; par[p] = L[p] = p-1; Grau[p-1]++;}
    else
      if (par[p-cL] < s) { Grau[par[p]]--; par[p] = par[s];  L[p] = L[s];  Grau[par[p]]++;}
      else { Grau[par[p]]--; par[p] = cL + par[p-cL]; Grau[par[p]]++; L[p] = 1+L[par[p]]; }

	++chi[par[p]];
    temp = rChi[par[p]];
    if (chi[par[p]] <= mc) {
       rChi[par[p]] = p;
       nextp[p] = chi[par[p]] < mc ? par[p] : nextp[par[p]];
       Gen( p+1, s, cL );               /* <==== recursive call */
       rChi[par[p]] = temp;
    }
	--chi[par[p]];

    nextp[p] = nextp[par[p]];
    np = nextp[p];
    while (np >= 1) {
       Grau[par[p]]--; par[p] = np; Grau[np]++; L[p] = 1 + L[np];
       ++chi[np];
       temp = rChi[np];  rChi[np] = p;
       if (chi[np] >= mc) nextp[p] = nextp[np];
       Gen( p+1, temp, p-temp );         /* <==== recursive call */
       --chi[np];
       rChi[par[p]] = temp;
       np = nextp[np];
       nextp[p] = np;
    }
  }
}

int main(){
int i;
for(n=1; n<=maxN; n++){
    mc = n-1;
    lb = 0;
    ub = n;
    num = 0;
    for( i=1; i<=n; i++)
        chi[i]=0;
    for (i=1; i<=lb+1; i++) {
        par[i] = L[i] = nextp[i] = i-1;
        rChi[i] = i+1;  chi[par[i]] = 1;
        }
    rChi[lb+1] = 0;
    Gen(lb+2, 0,  0);
    cout << an << ", ";
    }
return(0);
}